package org.xm.sk.controller.dbase;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.data.domain.Page;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.xm.sk.exception.DataNotFoundException;
import org.xm.sk.exception.RequestParamterException;
import org.xm.sk.service.data.BaseService;
import org.xm.sk.service.security.XmUser;
import org.xm.sk.vo.Base;
import org.xm.sk.vo.e.BoderStatus;
import org.xm.sk.vo.ob.Ids;
import org.xm.sk.vo.ob.MapList;
import org.xm.sk.vo.ob.MapList4Mete;
import org.xm.sk.vo.ob.MarkAv;
import org.xm.sk.vo.ob.MeteInfo;
import org.xm.sk.vo.ob.PageConf;
import org.xm.sk.vo.ob.PostMete;
import org.xm.sk.vo.ob.ResultMsg;
import org.xm.sk.vo.tb.Boder;
import org.xm.sk.vo.tb.Hairdresser;
import org.xm.sk.vo.tb.Mete;
import org.xm.sk.vo.tb.Shop;
import org.xm.sk.vo.tb.User;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import springfox.documentation.annotations.ApiIgnore;

@SuppressWarnings("unchecked")
@Api(tags = { "mete" })
@RestController
@RequestMapping(value="/metes")
public class MeteController {
    
    @Autowired
    private MessageSource messages;
    @Autowired
    private BaseService<Mete> meteService;
    @Autowired
    private BaseService<Boder> boderService;
    @Autowired
    private BaseService<User> userService;
    @Autowired
    private BaseService<Shop> shopService;
    @Autowired
    private BaseService<Hairdresser> hairdresserService;

    @Transactional
    @ApiOperation(value="创建评论", notes="根据mete对象创建评论，使用此接口需要ADMIN权限")
    @ApiImplicitParam(name = "mete", value = "评论详细实体mete", required = true, dataType = "Mete")
    @PreAuthorize("hasRole('ADMIN')")
    @RequestMapping(value="crt", method=RequestMethod.POST)
    public ResultMsg add(@RequestBody Mete mete) {
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        Boder boder = (Boder) boderService.findById(mete.getBoderId());
        if (Base.isValid(boder)) {
            boder.setStatus(BoderStatus.METED);
            boderService.update(boder);
        }
        Mete u = null;
        if (null != mete.getId() && 0 < mete.getId())
            u = (Mete) meteService.findById(mete.getId());
        else
            u = mete;
        u.getShops().clear();
        u.getHairdressers().clear();
        u.setComment(mete.getComment());
        u.setMark(mete.getMark());
        u.setName(mete.getName());
        u.setBoder(boder);
        if (null != mete.getShopId() && 0 < mete.getShopId()) {
            Shop shop = (Shop) shopService.findById(mete.getShopId());
            if (Base.isValid(shop)) {
                u.getShops().add(shop);
            } else {
                u.getShops().clear();
            }
        } else {
            u.getShops().clear();
        }
        if (null != mete.getHairdresserId() && 0 < mete.getHairdresserId()) {
            Hairdresser hairdresser = (Hairdresser) hairdresserService.findById(mete.getHairdresserId());
            if (Base.isValid(hairdresser)) {
                u.getHairdressers().add(hairdresser);
            } else {
                u.getHairdressers().clear();
            }
        } else {
            u.getHairdressers().clear();
        }
        User creator = (User) userService.findById(xmUser.getUserid());
        if (null != u.getId() && 0 < u.getId())
            meteService.update(u);
        else {
            u.setUser(creator);
            meteService.add(u);
        }
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }

    @ApiIgnore()
    @ApiOperation(value="删除评论", notes="根据URI的id来指定删除对象")
    @ApiImplicitParam(name = "id", value = "评论ID", required = true, paramType = "path", dataType = "int")
    @RequestMapping(value="/{id}", method=RequestMethod.DELETE)
    public ResultMsg delete(@PathVariable Integer id) {
        meteService.delete(id);
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }
    
    @ApiOperation(value="删除评论", notes="根据POST的id列表来指定删除对象，可批量")
    @ApiImplicitParam(name = "ids", value = "评论ID集", required = true, dataType = "Ids")
    @RequestMapping(value="/delete", method=RequestMethod.DELETE)
    public ResultMsg Batchdelete(@RequestBody Ids ids) {
        meteService.delete(ids.getIds());
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }
    
    @ApiIgnore()
    @ApiOperation(value="更新评论详细信息", notes="根据URI的id来指定更新对象，并根据传过来的mete信息来更新评论详细信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "评论ID", required = true, paramType = "path", dataType = "int"),
            @ApiImplicitParam(name = "mete", value = "待更新的评论详细实体mete", required = true, dataType = "Mete")
    })
    @RequestMapping(value="/{id}", method=RequestMethod.PUT)
    public ResultMsg update(@PathVariable Integer id, @RequestBody Mete mete) throws DataNotFoundException {
        Mete u = (Mete) meteService.findById(id);
        if (null == u) {
            throw new DataNotFoundException(Mete.class.getName());
        }
        mete.setId(id);
        meteService.update(mete);
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }

    @ApiIgnore()
    @ApiOperation(value="获取评论详细信息", notes="根据URI的id来获取评论详细信息")
    @ApiImplicitParam(name = "id", value = "评论ID", required = true, paramType = "path", dataType = "int")
    @RequestMapping(value="/{id}", method=RequestMethod.GET)
    public Mete load(@PathVariable Integer id) throws DataNotFoundException {
        Mete u = (Mete) meteService.findById(id);
        if (null == u) {
            throw new DataNotFoundException(Mete.class.getName());
        }
        return u;
    }
    
    @ApiOperation(value="获取评论列表", notes="根据提交的分页信息列出所以评论信息")
    @ApiImplicitParam(name = "pageConf", value = "分页信息实体", required = true, dataType = "PageConf")
    @RequestMapping(value={"/list"}, method=RequestMethod.POST)
    public MapList<Mete> list(@RequestBody PageConf pageConf) {
        List<Mete> u = null;
        Long allCount = null;
        Object o = meteService.findAllByPage(pageConf);
        if (o instanceof Page) {
            allCount = ((Page<Mete>) o).getTotalElements();
            u = ((Page<Mete>) o).getContent();
        } else {
            allCount = (long) ((List<Mete>) o).size();
            u = (List<Mete>) o;
        }
        for (Mete c : u) {
            if (null != c.getShops() && !c.getShops().isEmpty()) {
                Shop s = c.getShops().iterator().next();
                c.setShopId(s.getId());
                c.setShopName(s.getName());
            }
            if (null != c.getHairdressers() && !c.getHairdressers().isEmpty()) {
                Hairdresser s = c.getHairdressers().iterator().next();
                c.setHairdresserId(s.getId());
                c.setHairdresserName(s.getName());
                c.setHShopId(s.getShop().getId());
                c.setHShopName(s.getShop().getName());
            }
            if (null != c.getUser()) {
                User creator = c.getUser();
                if (Base.isValid(creator)) {
                    String creatorName = "";
                    if (null != creator.getNickname() && 0 < creator.getNickname().trim().length())
                        creatorName += creator.getNickname();
                    if (null != creator.getPhone() && 0 < creator.getPhone().trim().length()) {
                        if (0 < creatorName.length()) {
                            creatorName += ":" + creator.getPhone();
                        } else {
                            creatorName += creator.getPhone();
                        }
                    }
                    if (0 < creatorName.length()) {
                        c.setCreatorName(creatorName);
                    }
                }
            }
        }
        return new MapList<Mete>(allCount, u);
    }

    // --------------------- 业务具体接口 ---------------------
    
    protected MapList4Mete<MeteInfo> listMeteInfo(Object[] os) {
        Page<Mete> metes = (Page<Mete>) os[0];
        MarkAv markAv = (MarkAv) os[1];
        MarkAv markAv1 = null;
        if (2 < os.length)
            markAv1 = (MarkAv) os[2];
        List<MeteInfo> meteInfos = new ArrayList<MeteInfo>();
        for (Mete mete : metes.getContent()) {
            MeteInfo m = new MeteInfo();
            m.setId(mete.getId());
            for (Shop shop : mete.getShops()) {
                m.setShopId(shop.getId());
                break;
            }
            for (Hairdresser hairdresser : mete.getHairdressers()) {
                m.setHairdresserId(hairdresser.getId());
                break;
            }
            if (null != mete.getUser()) {
                User user = mete.getUser();
                m.setCreatorId(user.getId());
                if (null != user) {
                    m.setCreatorName(user.getName());
                    m.setCreatorNickName(user.getNickname());
                    m.setPhone(user.getPhone());
                    if (null != user.getImage())
                        m.setImageId(user.getImage().getId());
                }
            }
            m.setMark(mete.getMark());
            m.setComment(mete.getComment());
            m.setTime(mete.getCreatedate());
            meteInfos.add(m);
        }
        MapList4Mete<MeteInfo> m = new MapList4Mete<MeteInfo>();
        if (null != markAv) {
            m.setMarkAv(markAv.getValue());
        }
        if (null != markAv1) {
            m.setMarkAv1(markAv1.getValue());
        }
        m.setTotal(metes.getTotalElements());
        m.setRows(meteInfos);
        return m;
    }
    
    @ApiOperation(value="客户端获取评论列表", notes="根据提交的分页信息和评论所属信息列出所以评论信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "owner", value = "评论所属者", required = true, paramType = "path", dataType = "string"),
        @ApiImplicitParam(name = "ownerid", value = "评论所属者ID", required = true, paramType = "path", dataType = "int"),
        @ApiImplicitParam(name = "size", value = "每页数量", required = true, paramType = "path", dataType = "int"),
        @ApiImplicitParam(name = "page", value = "页码", required = true, dataType = "int", paramType = "path")
    })
    @PreAuthorize("hasAnyRole('ADMIN', 'CLIENT')")
    @RequestMapping(value={"/client/{owner}/{ownerid}/{size}/{page}"}, method=RequestMethod.GET)
    public MapList4Mete<MeteInfo> list(@PathVariable String owner, @PathVariable Integer ownerid, @PathVariable Integer size, @PathVariable Integer page) throws RequestParamterException {
        if (null == size || null == page || 1 > size || 0 > page) {
            throw new RequestParamterException();
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("owner", owner);
        map.put("ownerid", ownerid);
        Object[] os = (Object[]) meteService.findAllByPage(new PageConf(page, size), map);
        return listMeteInfo(os);
    }

    @ApiOperation(value="商家端获取发型师评论列表", notes="根据提交的分页信息列出所有发型师的评论信息")
    @ApiImplicitParam(name = "pageConf", value = "分页信息实体", required = true, dataType = "PageConf")
    @RequestMapping(value={"/mch/list"}, method=RequestMethod.POST)
    public MapList<Mete> mchList(@RequestBody PageConf pageConf) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("owner", "hairdresser");
        Object[] o = (Object[]) meteService.findAllByPage(pageConf, map);
        Long allCount = ((Page<Mete>) o[0]).getTotalElements();
        List<Mete> u = ((Page<Mete>) o[0]).getContent();
        for (Mete c : u) {
            if (null != c.getHairdressers() && !c.getHairdressers().isEmpty()) {
                Hairdresser s = c.getHairdressers().iterator().next();
                c.setHairdresserId(s.getId());
                c.setHairdresserName(s.getName());
                c.setHShopId(s.getShop().getId());
                c.setHShopName(s.getShop().getName());
            }
            if (null != c.getUser()) {
                User creator = c.getUser();
                if (Base.isValid(creator)) {
                    String creatorName = "";
                    if (null != creator.getNickname() && 0 < creator.getNickname().trim().length())
                        creatorName += creator.getNickname();
                    if (null != creator.getPhone() && 0 < creator.getPhone().trim().length()) {
                        if (0 < creatorName.length()) {
                            creatorName += ":" + creator.getPhone();
                        } else {
                            creatorName += creator.getPhone();
                        }
                    }
                    if (0 < creatorName.length()) {
                        c.setCreatorName(creatorName);
                    }
                }
            }
        }
        return new MapList<Mete>(allCount, u);
    }
    
    @ApiOperation(value="发型师端获取有关自己的评论列表", notes="根据提交的分页信息列出和发型师相关的所有评论信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "mark", value = "评分数", required = true, paramType = "path", dataType = "int"),
        @ApiImplicitParam(name = "size", value = "每页数量", required = true, paramType = "path", dataType = "int"),
        @ApiImplicitParam(name = "page", value = "页码", required = true, dataType = "int", paramType = "path")
    })
    @PreAuthorize("hasAnyRole('ADMIN', 'HAIRDRE')")
    @RequestMapping(value={"/hairdresser/{mark}/{size}/{page}"}, method=RequestMethod.GET)
    public MapList4Mete<MeteInfo> list4hairdresser(@PathVariable Integer mark, @PathVariable Integer size, @PathVariable Integer page) throws RequestParamterException {
        if (null == size || null == page || 1 > size || 0 > page) {
            throw new RequestParamterException();
        }
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        if (0 ==  xmUser.getHairdresserid()) {
            throw new RequestParamterException("当前用户非发型师用户，查无发型师信息");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("owner", "hairdresser");
        map.put("ownerid", xmUser.getHairdresserid());
        map.put("mark", mark);
        Object[] os = (Object[]) meteService.findAllByPage(new PageConf(page, size), map);
        return listMeteInfo(os);
    }
    
    @Transactional
    @ApiOperation(value="创建评论", notes="根据PostMete对象创建评论")
    @ApiImplicitParam(name = "postMete", value = "评论详细实体postMete", required = true, dataType = "PostMete")
    @PreAuthorize("hasAnyRole('ADMIN', 'CLIENT')")
    @RequestMapping(value="", method=RequestMethod.POST)
    public ResultMsg add(@RequestBody PostMete postMete) throws RequestParamterException {
        if (null == postMete.getOrderId() && 1 > postMete.getOrderId())
            throw new RequestParamterException("无效订单编号");
        Boder boder = (Boder) boderService.findById(postMete.getOrderId());
        if (!Base.isValid(boder))
            throw new RequestParamterException("无效订单编号");
        if (BoderStatus.METE != boder.getStatus())
            throw new RequestParamterException("当前订单状态不允评论");
        Mete mete = new Mete();
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        User creator = (User) userService.findById(xmUser.getUserid());
        mete.setUser(creator);
        mete.setCreator(xmUser.getUserid());
        mete.setComment(postMete.getComment());
        mete.setMark(postMete.getMark());
        mete.setBoder(boder);
        if ("shop".equals(postMete.getOwner().getName())) {
            Shop shop = (Shop) shopService.findById(postMete.getOwner().getId());
            if (null != shop) {
                Set<Shop> shops = new HashSet<Shop>(0);
                shops.add(shop);
                mete.setShops(shops);
            }
        } else if ("hairdresser".equals(postMete.getOwner().getName())) {
            Hairdresser hairdresser = (Hairdresser) hairdresserService.findById(postMete.getOwner().getId());
            if (null != hairdresser) {
                Set<Hairdresser> hairdressers = new HashSet<Hairdresser>(0);
                hairdressers.add(hairdresser);
                mete.setHairdressers(hairdressers);
            }
        }
        meteService.add(mete);
        boder.setStatus(BoderStatus.METED);
        boderService.update(boder);
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }
}
